package rollercoaster.railway;

import java.util.ArrayList;
import java.util.List;

import javax.media.opengl.GL2ES2;
import rollercoaster.commons.Model;
import rollercoaster.commons.Node;
import rollercoaster.commons.Vertex3D;
import rollercoaster.commons.interfaces.IVertexReader;
import rollercoaster.commons.interfaces.SurfaceTessellationAlgorithm;
import rollercoaster.railway.interfaces.BinarioDataReader;
import rollercoaster.railway.utils.BinarioParameterContainer;
import rollercoaster.railway.utils.PolePosition;
import rollercoaster.railway.utils.VertexUtils;

public class ClassicRailProducer extends RailProducer{

	public static final int numpaletti = 400;
	public static final float module=0.8f;
	
	public ClassicRailProducer(SurfaceTessellationAlgorithm tess,
			BinarioDataReader binarioReader, IVertexReader vertexReader) {
		super(tess, binarioReader, vertexReader);
	}

	public Node getNode(GL2ES2 gl) {
		
		BinarioParameterContainer bpc = initRailParameters(gl);
		Float radius = Float.parseFloat(bpc.getMiddlemap().get("tube-ray"));
		Tube middlesurface = new Tube(bpc.getTr(), new Circle(radius, new Vertex3D(0, 0, 0)), new Vertex3D(0, 0, 0));
		double angle=Math.PI/6;
		float x = (float) (module*Math.cos(angle));
		float y = (float) (module*Math.sin(angle));
		Float lateralradius = Float.parseFloat(bpc.getLateralmap().get("tube-ray"));
		Tube sxsurface = new Tube(bpc.getTr(), new Circle(lateralradius,new Vertex3D(0, 0, 0) ), new Vertex3D(-x,y, 0) );
		Tube dxsurface = new Tube(bpc.getTr(), new Circle(lateralradius,new Vertex3D(0, 0, 0) ), new Vertex3D(x,y, 0) );
		distanceBetweenRails=new Vertex3D(x, y, 0);
		
		float step=(middlesurface.getEndVPoint()-middlesurface.getStartVPoint())/numpaletti;
		List<Tube> tubicini = new ArrayList<Tube>();
		for (int i = 0; i < numpaletti; i++) {
			float v=i*step;
			float u=(float)angle/(2f*(float)Math.PI);
			Vertex3D p0=middlesurface.getTrajectory().getBase().gamma(v);
			Vertex3D p1=middlesurface.sigma(u, v);
			Vertex3D p2=sxsurface.sigma(u+0.5f, v);
			Vertex3D p3=sxsurface.sigma(u, v);
			Vertex3D start=VertexUtils.meanPoint(p0, p1);
			Vertex3D end=VertexUtils.meanPoint(p2, p3);
			Vertex3D start2=middlesurface.sigma(0.25f, v);
			Vertex3D end2=new Vertex3D(-start.getX()+end.getX()+start2.getX(), -start.getY()+end.getY()+start2.getY(), -start.getZ()+end.getZ()+start2.getZ());
			Trajectory seg=new Trajectory(new Segment(start,end),new Segment(start2, end2));
			Tube primopaletto=new Tube(seg, new Circle(Float.parseFloat(bpc.getLittlemap().get("tube-ray")), new Vertex3D(0, 0, 0)), new Vertex3D(0, 0, 0));
			tubicini.add(primopaletto);
			
			p1=middlesurface.sigma(0.5f-u, v);
			p2=dxsurface.sigma(1-u, v);
			p3=dxsurface.sigma(0.5f-u, v);
			start=VertexUtils.meanPoint(p0, p1);
			end=VertexUtils.meanPoint(p2, p3);
			start2=middlesurface.sigma(0.25f, v);
			end2=new Vertex3D(-start.getX()+end.getX()+start2.getX(), -start.getY()+end.getY()+start2.getY(), -start.getZ()+end.getZ()+start2.getZ());
			Trajectory seg2=new Trajectory(new Segment(start,end),new Segment(start2, end2));
			Tube secondopaletto=new Tube(seg2, new Circle(Float.parseFloat(bpc.getLittlemap().get("tube-ray")), new Vertex3D(0, 0, 0)), new Vertex3D(0, 0, 0));
			tubicini.add(secondopaletto);			
		}
		
		PolePosition positioner=new PolePosition(binarioReader.getSupportPositionInfo().get("support-position"));
		List<Float> positions=positioner.getPolePositions();
		List<Tube> pali = new ArrayList<Tube>();
		float h_base=-1.0f;
		for (Float float1 : positions) {
			Vertex3D top_pos=middlesurface.getTrajectory().getBase().gamma(float1);
			Segment seg=new Segment(new Vertex3D(top_pos.getX(), top_pos.getY(), h_base), top_pos);
			Segment seg_up=new Segment(new Vertex3D(top_pos.getX()+0.1f, top_pos.getY(), h_base), 
								new Vertex3D(top_pos.getX()+0.1f, top_pos.getY(), top_pos.getZ()));
			Trajectory traj=new Trajectory(seg, seg_up);
			Tube palone=new Tube(traj, new Circle(Float.parseFloat(bpc.getSupportmap().get("tube-ray")), new Vertex3D(0, 0, 0)), new Vertex3D(0, 0, 0));
			pali.add(palone);
		}
		
		List<Model> models = new ArrayList<Model>();
	
		Model middlemodel = produceModel(gl,bpc.getMaterialmap(), bpc.getMiddlemap(),
				middlesurface);
		models.add(middlemodel);
		Model sxmodel = produceModel(gl, bpc.getMaterialmap(),bpc.getLateralmap(),
				sxsurface);
		models.add(sxmodel);
		Model dxmodel = produceModel(gl, bpc.getMaterialmap(), bpc.getLateralmap(),
				dxsurface);
		models.add(dxmodel);
		
		for (Tube tubicino : tubicini) {
			Model tubicinomodel = produceModel(gl, bpc.getMaterialmap(), bpc.getLittlemap(),
					tubicino);
			models.add(tubicinomodel);
		}
		
		for (Tube palo : pali) {
			Model palomodel = produceModel(gl, bpc.getMaterialmap(), bpc.getSupportmap(),
					palo);
			models.add(palomodel);
		}
		
		return new Node(models);
	}



}
